<template>
  <div class="upload-box">
    <el-upload
      class="dg-upload"
      :class="[{'disabled':disabled}, {'picture-limit':limit&&fileList&&limit==fileList.length}]"
      :action="action"
      :name="name"
      :multiple="multiple"
      :show-file-list="fileListShow"
      :drag="drag"
      :accept="accept"
      :on-preview="pictureOnPreview"
      :on-remove="fileOnRemove"
      :list-type="fileListType"
      :file-list="fileList"
      :http-request="fileHttpRequest"
      :disabled="disabled"
      :limit="limit"
      :on-exceed="fileOnExceed">
      <slot></slot>
      <template v-if="drag">
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
      </template>
      <template v-else-if="uploadType === 'picture'">
        <template v-if="!fileListShow&&fileList&&fileList.length">
          <div v-if="disabled" class="upload-opera">
            <span class="opera-btn" @click="pictureOnPreview(fileList[0])"><i class="el-icon-zoom-in"></i></span>
          </div>
          <img :src="fileList[0].url" class="show-img">
        </template>
        <i v-if="fileListShow || (!fileListShow&&!fileList.length)" class="el-icon-plus img-loader-icon"></i>
      </template>
      <template v-else-if="uploadType === 'file' || uploadType === 'maxfile'">
        <el-button v-if="!disabled" size="small" :type="fileBtnType" :disabled="disabled">{{ btnName }}</el-button>
      </template>
    </el-upload>
    <span v-if="disabled&&(!fileList||!fileList.length)" class="disabled-empty color-999">无附件</span>
    <slot name="showtext"></slot>
    <el-button v-if="disabled&&batchDownload&&(fileList&&fileList.length)" type="text" @click="handleBatchDownload()">批量下载</el-button>
    <!-- image-viewer begin -->
    <el-image-viewer
      v-if="showViewer"
      :on-close="() => showViewer=false"
      :initial-index="intIndex"
      :url-list="picBigUrl"
      :z-index="9999" />
    <!-- image-viewer end -->
  </div>
</template>
<script>
import ElImageViewer from 'element-ui/packages/image/src/image-viewer';
import * as API_File from './api';

export default {
  name: 'DgFileUpload',
  components: { ElImageViewer },
  props: {
    action: {
      type: String,
      default: '/base-service/file'
    },
    name: {
      type: String,
      default: 'file'
    },
    fileBtnType: {
      type: String,
      default: 'primary'
    },
    btnName: {
      type: String,
      default: '点击上传'
    },
    multiple: Boolean,
    showFileList: {
      type: Boolean,
      default: true
    },
    drag: Boolean,
    accept: String,
    listType: {
      type: String,
      default: 'text' // text,picture,picture-card
    },
    fileDataList: {
      type: Array,
      default () {
        return [];
      }
    },
    disabled: Boolean,
    limit: Number,
    uploadType: String, // picture、file、maxfile
    // 上传文件储存的文件夹名
    fileNameTag: String,
    // 批量下载
    batchDownload: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      fileList: JSON.parse(JSON.stringify(this.fileDataList)),
      fileListType: this.listType, // 显示的导入文件类型
      fileListShow: this.showFileList, // 是否显示导入文件列表
      needDelFiles: [], // 需要删除的文件
      showViewer: false, // 图片详情组件
      intIndex: 0,
      picBigUrl: []
    };
  },
  watch: {
    fileDataList (_newVal) {
      this.$nextTick(() => {
        this.fileList = _newVal === null ? [] : JSON.parse(JSON.stringify(_newVal));
      });
    }
  },
  created () {
    if (this.uploadType === 'picture') {
      this.fileListType = 'picture-card';
    };
  },
  methods: {
    /**
      * @date 2021/07/15
      * @author wolfMan
      * @description {文件上传前格式校验}
    */
    fileBeforeUpload (file) {
      let _yesType = true;
      if (this.uploadType === 'picture') {
        _yesType = file.type === 'image/jpeg' || file.type === 'image/jpg' || file.type === 'image/png';
        if (!_yesType) {
          this.$msgError('上传图片只能是 JPG或PNG 格式!');
        };
      } else if (this.uploadType) {
        let _uploadTypeList = this.uploadType.split(';');
        for (let item of _uploadTypeList) {
          if (item === file.type) {
            _yesType = true;
            break;
          };
        };
        if (!_yesType) {
          this.$msgError('请上传正确的文件格式!');
        };
      };
      return _yesType;
    },
    /**
      * @date 2021/07/15
      * @author wolfMan
      * @description {上传超出提示}
    */
    fileOnExceed () {
      this.$msgError(`超过最大允许上传数量${this.limit}`);
    },
    /**
      * @date 2021/07/15
      * @author wolfMan
      * @description {文件上传}
    */
    fileHttpRequest (_content) {
      const _uploadType = this.uploadType;
      let _isPicture = _uploadType === 'picture';
      if (_isPicture || _uploadType === 'file' || _uploadType === 'maxfile') {
        let _params = new FormData();
        let _name = _isPicture ? 'uploadImages' : 'uploadFile';
        _params.append(_name, _content.file);
        // 文件存储位置文件夹名
        let _bizModule = this.fileNameTag || _uploadType;
        _params.append('bizModule', _bizModule);
        // 针对APK增加额外参数
        if (this.fileNameTag && this.fileNameTag === 'apk') {
          _params.append('originalFileName', 1);
        }
        Promise.resolve(_isPicture ? API_File.uploadPics(_params) : _uploadType === 'file' ? API_File.uploadFile(_params) : API_File.uploadMaxFile(_params)).then(response => {
          if (response && response.success) {
            let _fileUrl = _isPicture ? response.data[0].url : response.data.url;
            let _fileDataList = JSON.parse(JSON.stringify(this.fileDataList)) || [];
            if (_uploadType && !this.fileListShow) {
              _fileDataList = [{
                name: _content.file.name,
                url: _fileUrl,
                uid: _content.file && _content.file.uid ? _content.file.uid : undefined
              }];
              this.$nextTick(() => {
                this.fileList = _fileDataList;
                this.$forceUpdate();
              });
            } else {
              _fileDataList.push({
                name: _content.file.name,
                url: _fileUrl,
                uid: _content.file && _content.file.uid ? _content.file.uid : undefined
              });
            };
            this.$emit('update:fileDataList', _fileDataList);
          } else {
            this.$msgError(response.msg);
          };
        });
      };
    },
    /**
      * @date 2021/07/15
      * @author wolfMan
      * @description {图片预览}
    */
    pictureOnPreview (file) {
      // 当前文件类型
      let _type = file.url ? file.url.split('.').splice(-1)[0] : 'jpg';
      if (['png', 'jpg', 'jpeg'].includes(_type)) {
        let _imgList = [];
        this.fileList.forEach(item => {
          // 遍历出所有图片类型文件
          if (item.url && ['png', 'jpg', 'jpeg'].includes(item.url.split('.').splice(-1)[0])) {
            _imgList.push(item.url);
          };
        });
        let _intIndex = _imgList.indexOf(file.url);
        this.intIndex = _intIndex === -1 ? 0 : _intIndex;
        this.picBigUrl = _imgList;
        this.showViewer = true;
      } else {
        window.open(file.url);
      };
    },
    /**
      * @date 2021/07/15
      * @author wolfMan
      * @description {文件删除}
    */
    fileOnRemove (_delItem) {
      let _fileDataList = JSON.parse(JSON.stringify(this.fileDataList));
      if (_delItem.status === 'success') {
        // 储存需要删除的历史文件，等页面提交时统一删除c
        this.needDelFiles.push(_delItem.url);
      };
      let _needDelIndex = _fileDataList.findIndex(item => item.url === _delItem.url);
      if (_needDelIndex > -1) {
        // 直接删除本次编辑新增的文件
        // this.delFiles(_fileDataList[_needDelIndex].url);
        _fileDataList.splice(_needDelIndex, 1);
      };
      this.$emit('update:fileDataList', _fileDataList);
    },
    /**
      * @date 2021/07/15
      * @author wolfMan
      * @description {删除文件}
    */
    delFiles (_needDel) {
      if (!_needDel && !this.needDelFiles.length) {
        return;
      };
      let _params = {
        urls: _needDel ? [_needDel] : this.needDelFiles
      };
      API_File.delFileByUrls(_params).then(respons => {
        // 清空需要删除的文件
        if (!_needDel) {
          this.needDelFiles = [];
        };
        console.log(respons.message);
      });
    },
    /**
      * @date 2022/12/13
      * @author wolfMan
      * @description {批量下载文件压缩包 batchDownload}
    */
    handleBatchDownload () {
      const _params = this.fileList.map(item => {
        return {
          name: item.name,
          url: item.url
        };
      });
      API_File.batchDownload(_params).then(response => {
        const aLink = document.createElement('a');
        var blob = new Blob([response], { type: 'application/zip' });
        aLink.href = URL.createObjectURL(blob);
        aLink.setAttribute('download', '批量下载'); // 设置下载文件名称
        document.body.appendChild(aLink);
        aLink.click();
        document.body.appendChild(aLink);
      });
    },
    /**
      * @date 2021/07/16
      * @author wolfMan
      * @description {重置列表}
    */
    restFiles () {
      this.$emit('update:fileDataList', []);
    }
  }
};
</script>

<style lang="scss" scoped>
.upload-box {
  display: inline-block;
}
::v-deep .dg-upload {
  .el-upload {
    position: relative;
    overflow: hidden;
    .show-img {
      width: 100%;
      height: 100%;
      background: #f9f9f9;
    }
    .upload-opera {
      position: absolute;
      left: 0;
      top: 0;
      z-index: 3;
      width: 100%;
      height: 100%;
      line-height: 148px;
      text-align: center;
      cursor: default;
      opacity: 0;
      transition: opacity .3s;
      background-color: rgba(0, 0, 0, .5);
      .opera-btn {
        display: none;
        justify-content: center;
        align-items: center;
        line-height: 40px;
        cursor: pointer;
        & + .opera-btn {
          margin-left: 15px;
        }
        i {
          color: #fff;
          font-size: 30px;
        }
      }
      &:hover {
        opacity: 1;
        .opera-btn {
          display: inline-flex;
        }
      }
    }
  }
  &.license {
    .el-upload {
      width: 280px;
      height: 198px;
      line-height: 220px;
      .el-icon-plus {
        font-size: 60px;
      }
    }
  }
  .el-upload-list--picture-card {
    line-height: 0;
  }
  .el-upload--picture-card {
    line-height: 156px;
    .el-upload-dragger {
      width: 146px;
      height: 146px;
      line-height: 0;
      border: none;
      background: unset;
      .el-icon-upload {
        margin: 30px 0 10px 0;
      }
      .el-upload__text {
        padding: 0 20px;
        line-height: 20px;
      }
    }
  }
  &.picture-limit {
    .el-upload--picture-card {
      display: none;
    }
  }
  .is-disabled {
    .el-upload-list__item:first-child {
      margin-top: 0;
    }
    &.el-upload-list--text {
      .el-upload-list__item:first-child {
        margin-top: 5px;
      }
    }
    + .el-upload {
      display: none;
    }
  }
  &.disabled {
    .el-upload--text {
      display: none;
    }
  }
}
</style>
<style lang="scss">
  .upload-img-tip {
    padding-top: 5px;
    line-height: 20px;
    color: #999;
    font-size: 12px;
  }
</style>
